package com.msz.util;

import com.alibaba.fastjson.JSON;
import com.msz.domain.User;
import com.msz.exception.JwtException;
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * JWT加密与解密工具类
 * 在进行BASE64编码时需要JAXB API，在JDK1.8版本以上已被移除
 * 方案一：JDK版本选择1.8
 * 方案二：手动引入 jaxb-api-2.3.1.jar
 * @author hx
 */
public class JwtUtils {

    /**
     * token过期时间 5分钟
     */
    public static final long EXPIRE =  1000 * 60 * 5;
    /**
     * 签名 - 私钥
     */
    public static final String SIGN = "abc123";

    /**
     * 生成token
     * @param user 用户
     * @return
     */
    public static String generatorJwtToken(User user){
        if (StringUtils.isEmpty(user)) {
            throw new JwtException(500,"参数为空");
        }
        //将对象转换成json字符串进行传输
        String userJson = String.valueOf(JSON.toJSON(user));


        String jwtToken = Jwts.builder()

                //设置jwt头信息Header
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                //设置签发时间,以毫秒存储
                .setIssuedAt(new Date())

                //设置过期时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))

                //Payload有效载荷
                //设置token主体部分 ，存储用户信息，存储对象时需进行JSON转换
                .claim("user", userJson)
                //编码方式和签名
                .signWith(SignatureAlgorithm.HS256, SIGN)

                //编码压缩
                .compact();

        return jwtToken;
    }



    /**
     * 验证请求并返回负载信息
     * @param request 请求
     * @return 负载信息
     */
    public static User verifyToken(HttpServletRequest request) {
        String requestToken = request.getHeader("token");
        if(StringUtils.isEmpty(requestToken)) {
            throw new JwtException(600,"请先登录!");
        }

        Jws<Claims> claimsJws = null;
        try {
            //解密token
            claimsJws = Jwts.parser().setSigningKey(SIGN).parseClaimsJws(requestToken);
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            throw new JwtException(601,"登录超时,请重新登录");
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
            throw new JwtException(602,"不支持的JWT");
        } catch (MalformedJwtException e) {
            e.printStackTrace();
            throw new JwtException(603,"JWT格式错误");
        } catch (SignatureException e) {
            e.printStackTrace();
            throw new JwtException(604,"签名异常");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new JwtException(605,"非法请求");
        }catch (Exception e) {
            e.printStackTrace();
            throw new JwtException(606,"JWT解析异常");
        }
        Claims claims = claimsJws.getBody();
        //先将对象转为json字符串
        String userJson = (String) claims.get("user");
        //再将json转换为User对象
        User user = JSON.parseObject(userJson, User.class);
        return user;

    }

    /**
     * 检测token信息
     * @param token
     * @return
     */
    public static Jws<Claims> checkToken(String token) {
        Jws<Claims> claimsJws = null;
        try {
            claimsJws = Jwts.parser().setSigningKey(SIGN).parseClaimsJws(token);
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            throw new JwtException(601,"登录超时,请重新登录");
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
            throw new JwtException(602,"不支持的JWT");
        } catch (MalformedJwtException e) {
            e.printStackTrace();
            throw new JwtException(603,"JWT格式错误");
        } catch (SignatureException e) {
            e.printStackTrace();
            throw new JwtException(604,"签名异常");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new JwtException(605,"非法请求");
        }catch (Exception e) {
            e.printStackTrace();
            throw new JwtException(606,"JWT解析异常");
        }
        return claimsJws;
    }
    /**
     * {
     *     "code": 200,
     *     "message": "检测成功",
     *     "data": {
     *          //对json进行base64加密 token第一段
     *         "header": {
     *             "typ": "JWT",
     *             "alg": "HS256"
     *         },
     *         "body": {
     *              //
     *             "iat": 1638690032, //签发时间
     *             "exp": 1638690632, //过期时间
     *             "user": {
     *                 "id": 2,
     *                 "username": "test1",
     *                 "password": "123",
     *                 "sex": "女",
     *                 "birthday": 999302400000
     *             }
     *         },
     *         "signature": "jW6Mms2UaR9QGIfSImTYCeScBF_Ud3HC9_XAEpybYx8"
     *         秘钥加盐
     *     }
     * }
     */


}
